package com.zeedev.flyingsaucer.data;

import android.database.sqlite.SQLiteQueryBuilder;
import android.text.TextUtils;
import com.zeedev.flyingsaucer.data.Command.Operator;
import mobi.zeedev.flyingsaucer.common.DataModule.MetaBeer;

import java.io.Serializable;
import java.util.*;
import java.util.Map.Entry;

public class BeerFilter implements Serializable {
		
	//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
	// Constants
	//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

	public static final String TAG = "BeerFilter";
	public static final String BEER_FILTER = "BEER_FILTER";

	public enum ContainerType {
		CAN,
		BOTTLED,
		DRAUGHT,
		ALL
	}
	
	public enum TastedType {
		TASTED,
		NOT_TASTED,
		ALL
	}

	//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
	// Variables  / State
	//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX	

	Map<String, Set<String>> propertySelectionValuesMap;
	
	ContainerType containerType = null;
	TastedType tastedType = null;	
	private List<SQLFormattable> commandList = null;

	//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
	// Constructors/Constants
	//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

	public BeerFilter(){
		super();
		//propertySelectionValuesMap = new HashMap<String, Set<String> >();
		propertySelectionValuesMap = Collections.synchronizedMap(new HashMap<String, Set<String> > ());
		containerType = ContainerType.ALL;
		tastedType = TastedType.ALL;	
		commandList = new ArrayList<SQLFormattable>();		
	}
	
	public BeerFilter(TastedType tastedType2, ContainerType containerType2) {
		this();
		if ( tastedType2 != null ) {
			this.tastedType = tastedType2;
		}
		if ( containerType2 != null ) {
			this.containerType = containerType2;
		}
	}

	//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
	// Getters / Setters (Chaining Enabled)
	//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
	
	public ContainerType getContainerType() {
		return containerType;
	}

	public BeerFilter setContainerType(ContainerType containerType) {
		this.containerType = containerType;
		return this;
	}

	public TastedType getTastedType() {
		return tastedType;
	}

	public BeerFilter setTastedType(TastedType tastedType) {
		this.tastedType = tastedType;
		return this;
	}
	
	public List<SQLFormattable> getCommandList() {
		return commandList;
	}

	public BeerFilter setCommandList(List<SQLFormattable> commandList) {
		this.commandList = commandList;
		return this;
	}

	public Map<String, Set<String>> getPropertySelectionValuesMap() {
		return propertySelectionValuesMap;
	}

	public void setPropertySelectionValuesMap(
			Map<String, Set<String>> propertySelectionValuesMap) {
		this.propertySelectionValuesMap = propertySelectionValuesMap;
	}
	
	public Set<String> getGroupedSelectionSet(String groupBy) {
		Set<String> tset = this.propertySelectionValuesMap.get(groupBy);
		if (tset == null){
			propertySelectionValuesMap.put(groupBy, new HashSet<String>());	
		}
		return this.propertySelectionValuesMap.get(groupBy);
	}
	
	public Boolean hasSelection() {
		Boolean ret = false;
		for (String curKey: this.propertySelectionValuesMap.keySet() ) {
			ret = ret || !this.propertySelectionValuesMap.get(curKey).isEmpty();
		}
		ret = ret || !this.propertySelectionValuesMap.isEmpty();
		return ret;
	}
	
	public Boolean hasOneEmptySelection() {
		Boolean ret = false;
		for (Entry <String, Set<String>>  entry: this.propertySelectionValuesMap.entrySet() ) {
			if (entry.getValue().isEmpty()) {
				return true;
			}
		}
		return ret;
	}
		
	//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
	// Business Logic
	//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
	
	public SQLiteQueryBuilder getSQLBuilder(String TABLE_NAME) {
		SQLiteQueryBuilder build = new SQLiteQueryBuilder();
		List<String> queryList = new ArrayList<String>();
//		Map<String, String> columnProject = new HashMap<String,String>();
//		columnProject.put(MetaBeer.DB_ID, MetaBeer.DB_ID);
//		columnProject.put(MetaBeer.STATUS, MetaBeer.STATUS);
//		columnProject.put(MetaBeer.DRAUGHT, MetaBeer.DRAUGHT);
//		columnProject.put(MetaBeer.BOTTLE, MetaBeer.BOTTLE);
//		columnProject.put(MetaBeer.TASTED, MetaBeer.TASTED);
		
		//FROM
		build.setTables(TABLE_NAME);
		
		//SELECT COLUMNS
		//AUTOMATIC w/ QUERIES?
		
		//WHERE PROPERTIES
		//StringBuilder sb = new StringBuilder();
		String cur = "";
		//String test2 = "";
		
		
		
		for (int i = 0; i < commandList.size(); i++) {
			SQLFormattable cmd = commandList.get(i);
			if (cmd.isComplete()) {	
				//build.appendWhere(MetaBeer.INTERNAL_DATE_ADDED + " <> ");
				//build.appendWhereEscapeString(String.valueOf(originDate.getTime()));
				//build.appendWhere(cmd.getPredicate());
				//build.appendWhere(cmd.getPropertyValue());
				build.appendWhere(cmd.getFormattedSQL());	
				//build.appendWhereEscapeString(cmd.getPropertyValue());
				cur = cmd.toString();
				//columnProject.putAll(cmd.getColumnsAsMapDup());
				if (i != commandList.size() -1) {
					build.appendWhere(" AND ");
				}
			}
		}
		
		if ( !TextUtils.isEmpty(cur) && tastedType != null && tastedType != TastedType.ALL) {
			build.appendWhere(" AND ");
		}
		switch (tastedType) {
//		case ALL:
//			cur = "";
//			break;
		case NOT_TASTED:
			//cur = build.buildQuery(new String[] { MetaBeer.TASTED } , MetaBeer.TASTED + " = ?", new String[] { String.valueOf((int)0) }, null, null, null, null);
			cur = MetaBeer.TASTED + " = " + String.valueOf(0) ; 
			build.appendWhere(MetaBeer.TASTED + " = ");
			build.appendWhereEscapeString(String.valueOf(0));
			break;
		case TASTED:
			//cur = build.buildQuery(new String[] { MetaBeer.TASTED } , MetaBeer.TASTED + " = ?", new String[] { String.valueOf((int)1) }, null, null, null, null);
			cur = MetaBeer.TASTED + " = " + String.valueOf(1) ; 
			build.appendWhere(MetaBeer.TASTED + " = ");
			build.appendWhereEscapeString(String.valueOf(1));
			break;
//		default:
//			cur = "";
		}
		if (!TextUtils.isEmpty(cur)) {
			queryList.add(cur);
		}
		
		if ( !TextUtils.isEmpty(cur) && containerType != null && containerType != ContainerType.ALL) {
			build.appendWhere(" AND ");
		}
		
		switch (containerType) {
//		case ALL:
//			cur = "";
//			break;
		case DRAUGHT:
			//cur = build.buildQuery(new String[] { MetaBeer.DRAUGHT } , MetaBeer.DRAUGHT + " = ?", new String[] { String.valueOf((int)1) }, null, null, null, null);
			cur = MetaBeer.DRAUGHT + " = " + String.valueOf(1) ; 
			build.appendWhere(MetaBeer.DRAUGHT + " = ");
			build.appendWhereEscapeString(String.valueOf(1));
			break;
		case BOTTLED:
			cur = MetaBeer.BOTTLE + " = " + String.valueOf(1) ;
			//cur = build.buildQuery(new String[] { MetaBeer.BOTTLE } , MetaBeer.BOTTLE + " = ?", new String[] { String.valueOf((int)1) }, null, null, null, null);
			build.appendWhere(MetaBeer.BOTTLE + " = ");
			build.appendWhereEscapeString(String.valueOf(1));
			break;
		default: 
			//FilterType.ALL
			//fall back
//			cur ="";
//			break;
		}
		if (!TextUtils.isEmpty(cur)) {
			queryList.add(cur);
		}
		
		if ( !TextUtils.isEmpty(cur) ) {
			build.appendWhere(" AND ");
		}
		build.appendWhere(MetaBeer.STATUS + " = ");
		build.appendWhereEscapeString( MetaBeer.STATUS_ACTIVE );
		cur = MetaBeer.STATUS + " = " + MetaBeer.STATUS_ACTIVE ;
		if (!TextUtils.isEmpty(cur)) {
			queryList.add(cur);
		}
		
		//build.setProjectionMap( columnProject );
		
		return build;
	}
	
	public SQLiteQueryBuilder getSQLBuilder2(String[] someProjection) {
		
		List<String> qList = new ArrayList<String>();
		Map<String, String> columnProjection = new HashMap<String,String>();
		columnProjection.put(MetaBeer.DB_ID, MetaBeer.DB_ID);
		//columnProjection.put(MetaBeer.STATUS, MetaBeer.STATUS);
		columnProjection.put(MetaBeer.DRAUGHT, MetaBeer.DRAUGHT);
		columnProjection.put(MetaBeer.BOTTLE, MetaBeer.BOTTLE);
		//columnProjection.put(MetaBeer.TASTED, MetaBeer.TASTED);
		columnProjection.put(MetaBeer.NAME, MetaBeer.NAME);
		columnProjection.put(MetaBeer.CAN, MetaBeer.CAN);
		columnProjection.put(MetaBeer.BEER_ID, MetaBeer.BEER_ID);
	
		
		for (Entry<String,Set<String>> entry: this.propertySelectionValuesMap.entrySet()) {
//			if (!TextUtils.isEmpty(entry.getKey())) {//entry.getKey() != null
//				String sql = BeerFilter.getCommandSql(entry.getKey(), entry.getValue());
//				if (!TextUtils.isEmpty(sql)) {
//					qList.add(sql);
//					columnProjection.put(entry.getKey(), entry.getKey());
//				}
//			}
			
			SQLFormattable ccmd = new ComplexCommand(entry.getKey(), entry.getValue());
			commandList.add(ccmd);
			
		}
		
		switch (tastedType) {
		case NOT_TASTED:
			Command tastedCommand = new Command(MetaBeer.TASTED, String.valueOf(0), Operator.EQUAL, false);
			commandList.add(tastedCommand);
			break;
		case TASTED:
			Command notTastedCommand = new Command(MetaBeer.TASTED, String.valueOf(1), Operator.EQUAL, false);
			commandList.add(notTastedCommand);
			break;
		}

		
		switch (containerType) {

		case DRAUGHT:
			Command draughtCommand = new Command(MetaBeer.DRAUGHT, String.valueOf(1), Operator.EQUAL, false);
			commandList.add(draughtCommand);
			break;
		case BOTTLED:
			Command bottledCommand = new Command(MetaBeer.BOTTLE, String.valueOf(1), Operator.EQUAL, false);
			commandList.add(bottledCommand);
			break;
		default: 
		}

		
		//qList.add(MetaBeer.STATUS + " = " + "'" + MetaBeer.STATUS_ACTIVE + "'" );
		//String property, String propertyValue, Operator operator
		Command statusCommand = new Command(MetaBeer.STATUS, MetaBeer.STATUS_ACTIVE, Operator.EQUAL);
		commandList.add(statusCommand);
		
		
		for (int i = 0; i < commandList.size(); i++) {
			SQLFormattable cmd = commandList.get(i);
			if (cmd.isComplete()) {	
				//String curWhereClaus = cmd.getPredicate() + cmd.getPropertyValue();
				qList.add(cmd.getFormattedSQL());
				columnProjection.putAll(cmd.getColumns());
			}
		}
		
		SQLiteQueryBuilder build = new SQLiteQueryBuilder();
		
		for (int i = 0 ; i < qList.size(); i++) {
			String t = qList.get(i);
			if (!TextUtils.isEmpty(t)) {
				build.appendWhere(t);
				if (i != qList.size() - 1) {
					build.appendWhere(" AND ");
				}
			}
		}
		
		for (String cur: someProjection) {
			columnProjection.put(cur, cur);
		}
		
		//build.setTables(someProjection);
		build.setProjectionMap( columnProjection );
		
		return build;
	}
		
	//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
	// Utility
	//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
	

	
	
}
